package com.gitee.wsl.text.keyword

import com.gitee.wsl.ext.string.isSurround

/**
 * 字符串模式匹配，使用${XXXXX}作为变量，例如：
 *
 * <pre>
 * pattern: ${name}-${age}-${gender}-${country}-${province}-${city}-${status}
 * text:    "小明-19-男-中国-河南-郑州-已婚"
 * result:  {name=小明, age=19, gender=男, country=中国, province=河南, city=郑州, status=已婚}
</pre> *
 *
 * @author looly
 * @since 5.6.0
 */
class QuickMatcher(pattern: String) {

    var patterns: List<String> = parse(pattern)

    /**
     * 匹配并提取匹配到的内容
     *
     * @param text 被匹配的文本
     * @return 匹配的map，key为变量名，value为匹配到的值
     */
    fun match(text: String): Map<String, String> {
        val result =  mutableMapOf<String, String>()
        var from = 0
        var key: String? = null
        var to: Int
        for (part in patterns) {
            if (part.isSurround( "\${", "}")) {
                // 变量
                key = part.substring( 2, part.length - 1)
            } else {
                to = text.indexOf(part, from)
                if (to < 0) {
                    //普通字符串未匹配到，说明整个模式不能匹配，返回空
                    return emptyMap()
                }
                if (null != key && to > from) {
                    // 变量对应部分有内容
                    result.put(key, text.substring(from, to))
                }
                // 下一个起始点是普通字符串的末尾
                from = to + part.length
                key = null
            }
        }

        if (null != key && from < text.length) {
            // 变量对应部分有内容
            result.put(key, text.substring(from))
        }

        return result
    }

    companion object {
        /**
         * 解析表达式
         *
         * @param pattern 表达式，使用${XXXX}作为变量占位符
         * @return 表达式
         */
        private fun parse(pattern: String): List<String> {
            val patterns = ArrayList<String>()
            val length = pattern.length
            var c = 0.toChar()
            var pre: Char
            var inVar = false
            val part= StringBuilder()
            for (i in 0..<length) {
                pre = c
                c = pattern.get(i)
                if (inVar) {
                    part.append(c)
                    if ('}' == c) {
                        // 变量结束
                        inVar = false
                        patterns.add(part.toString())
                        part.setLength(0)
                    }
                } else if ('{' == c && '$' == pre) {
                    // 变量开始
                    inVar = true
                    val preText = part.substring(0, part.length - 1)
                    if (preText.isNotEmpty()) {
                        patterns.add(preText)
                    }
                    part.setLength(0)
                    part.append(pre).append(c)
                } else {
                    // 普通字符
                    part.append(c)
                }
            }

            if (part.isNotEmpty()) {
                patterns.add(part.toString())
            }
            return patterns
        }
    }
}
